import requests
import json
import base64
import hmac
import hashlib
import time
import uuid
import os
from ..exceptions import PlatformAPIException, PlatformRequestException, PlatformNotSupportSymbolException, PlatformClientException
from ..restapibase import RestAPIBase
from MarketData.const import CONST
from .symbols import symbols
from Platforms.key import COMMODITY, BASE


class BigoneRESTAPI(RestAPIBase):
    """docstring for BitfinexRESTAPI"""

    def __init__(self, api_key, secret_key, isdebug=False):
        self.api_key = api_key
        self.api_secret = str(uuid.uuid1())
        self.isdebug = isdebug
        self.url = 'https://api.big.one'

    def _debug(self, result):
        if self.isdebug:
            print(result)

    def _get_auth(self):
        headers = {'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36',
                   'Authorization': 'Bearer ' + self.api_key,
                   'Big-Device-Id': self.api_secret,
                   'Content-Type': 'application/json'}
        return headers

    def _get(self, endpoint, params={}):
        url = self.url + endpoint
        headers = self._get_auth()
        # self._debug(json.dumps(params))
        response = requests.get(url, headers=headers,
                                params=json.dumps(params))

        rescode = response.status_code
        restext = response.text
        self._debug(str(rescode) + '|' + restext)
        errmsg = 'StatusCode: GET %s \nURL:%s \nParams: %s \nResponse: %s' % (
            rescode, url, str(params), restext)
        response = response.json()

        if response != None:
            if rescode == 200:
                return response
            else:
                raise PlatformAPIException(errmsg)
        else:
            raise PlatformRequestException(errmsg)

    def _del(self, endpoint, params={}):
        url = self.url + endpoint
        headers = self._get_auth()
        # self._debug(json.dumps(params))
        response = requests.delete(url, headers=headers,
                                   params=json.dumps(params))

        rescode = response.status_code
        restext = response.text
        self._debug(str(rescode) + '|' + restext)
        errmsg = 'StatusCode: DELETE %s \nURL:%s \nParams: %s \nResponse: %s' % (
            rescode, url, str(params), restext)
        response = response.json()

        if response != None:
            if rescode == 200:
                return response
            else:
                raise PlatformAPIException(errmsg)
        else:
            raise PlatformRequestException(errmsg)

    def _post(self, endpoint, data={}):
        url = self.url + endpoint
        # self._debug(url)
        headers = self._get_auth()
        response = requests.post(url, headers=headers,
                                 data=json.dumps(data), verify=True)
        self._debug(response.status_code)

        rescode = response.status_code
        restext = response.text
        self._debug(str(rescode) + '|' + restext)
        errmsg = 'StatusCode: POST %s \nURL:%s \nData: %s \nResponse: %s' % (
            rescode, url, str(data), restext)
        response = response.json()

        if response != None:
            if rescode == 200:
                return response
            else:
                raise PlatformAPIException(errmsg)
        else:
            raise PlatformRequestException(errmsg)

    # EndPoints
    def _symbols(self):
        url = '/markets'
        resjson = self._get(url)
        self._debug('symbols: \n' + json.dumps(resjson, indent=2))

        result = []
        for res in resjson["data"]:
            result.append(res["symbol"])
        sw = open(os.path.dirname(
            os.path.realpath(__file__)) + '/symbols.py', 'w')
        sw.write('symbols = ' + str(result))
        sw.close()

        self._debug('symbols: \n' + str(result))
        return result

    def _order(self, symbol, side, ordertype, amount, price):
        url = '/orders'
        data = {
            "order_market": symbol,
            "order_side": side,
            "price": str(price),
            "amount": str(amount),
        }
        self._debug("data: " + json.dumps(data, indent=2))
        resjson = self._post(url, data)
        result = {"id": resjson["data"]["order_id"]}
        return result

    # Public
    def get_currency(self, currency):
        """[summary]

        Arguments:
            currency {[type]} -- [description]

        Returns:
            [type] -- [description]
        """

        return currency.upper()

    def get_symbol(self, commodity, base):
        result = commodity.upper() + '-' + base.upper()
        if not (result in symbols):
            errmsg = 'Not supported: %s' % result
            raise PlatformNotSupportSymbolException(errmsg)

        return result

    def get_ticker(self, symbol):
        '''[summary]

        [description]

        Arguments:
            symbol {[type]} -- [description]

        Returns:
            [type] -- [{
                  "mid": "0.029707",
                  "ask": "0.029728",
                  "volume": "263353.6641857",
                  "high": "0.036467",
                  "low": "0.029049",
                  "bid": "0.029686",
                  "last_price": "0.02972",
                  "timestamp": "1512632242.711332"
                }]
        '''
        raise NotImplementedError()

    def get_depth(self, symbol):
        '''
        [description]

        Arguments:
            symbol {[type]} -- [description]

        Returns:
            {
              "bids": [
                {
                  "price": "0.029678",
                  "amount": "22.88434254",
                  "timestamp": "1512632248.0"
                }],
                "asks": [
                    {
                      "price": "0.029739",
                      "amount": "1.0035",
                      "timestamp": "1512632248.0"
                }]
            }
        '''
        url = '/markets/' + symbol + '/book'
        params = {
            'type': 'both'
        }
        resjson = self._get(url, params)

        result = {'bids': resjson['data']['bids'],
                  'asks': resjson['data']['asks']}
        self._debug('get_depth: \n' + json.dumps(result, indent=2))
        return result

    def get_account(self):
        raise NotImplementedError()

    def get_balances(self, type='trade'):
        url = '/accounts'

        resjson = self._get(url)

        result = {}

        for account in resjson['data']:
            result[account['account_type']] = account['active_balance']

        # result[account['account_type']] = account['active_balance']
        self._debug('account: \n' + json.dumps(result, indent=2))
        return result

    def limit_buy(self, symbol, amount, price):
        '''[summary]

        [description]

        Arguments:
            symbol {[type]} -- [description]
            amount {[type]} -- [description]
            price {[type]} -- [description]

        Returns:
            [type] -- [description]
        '''
        result = self._order(symbol, 'BID', 'LIMIT', amount, price)
        self._debug('limit_buy: \n' + json.dumps(result, indent=2))
        return result

    def limit_sell(self, symbol, amount, price):
        '''[summary]

        [description]

        Arguments:
            symbol {[type]} -- [description]
            amount {[type]} -- [description]
            price {[type]} -- [description]

        Returns:
            [type] -- [description]
        '''
        result = self._order(symbol, 'ASK', 'LIMIT', amount, price)
        self._debug('limit_sell: \n' + json.dumps(result, indent=2))
        return result

    def market_buy(self, symbol, amount, price):
        '''[summary]

        [description]

        Arguments:
            symbol {[type]} -- [description]
            amount {[type]} -- [description]
            price {[type]} -- [description]

        Returns:
            [type] -- [description]
        '''
        result = self._order(symbol, 'BID', 'LIMIT', amount, "%.7f" % (
            float(price) * (1 + CONST.Slippage_synMarket)))
        self._debug('limit_buy: \n' + json.dumps(result, indent=2))
        return result

    def market_sell(self, symbol, amount, price):
        '''[summary]

        [description]

        Arguments:
            symbol {[type]} -- [description]
            amount {[type]} -- [description]
            price {[type]} -- [description]

        Returns:
            [type] -- [description]
        '''
        result = self._order(symbol, 'ASK', 'LIMIT', amount, "%.7f" % (
            float(price) * (1 - CONST.Slippage_synMarket)))
        self._debug('limit_sell: \n' + json.dumps(result, indent=2))
        return result

    def get_order(self, symbol, order_id):
        '''[summary]

        [description]

        Arguments:
            symbol {[type]} -- [description]
            order_id {[type]} -- [description]

        Returns:
            [type] -- [description]
        '''
        url = '/orders/' + order_id
        resjson = self._get(url)

        self._debug('get_order: \n' + json.dumps(resjson, indent=2))
        return resjson

    def get_all_orders(self, symbol=''):

        legal_symbols = []
        if symbol == '':
            for ba in BASE:
                for com in COMMODITY:
                    if ba != com:
                        try:
                            legal_symbols.append(self.get_symbol(com, ba))
                        except PlatformNotSupportSymbolException:
                            pass
        else:
            legal_symbols.append(symbol)
        self._debug('[GET] get_open_orders:\n' +
                    json.dumps(legal_symbols, indent=2))

        result = []

        for sym in legal_symbols:
            url = '/orders' + '?market=' + sym
            resjson = self._get(url)['data']
            for res in resjson:
                result.append(res)
            self._debug('[GET] get_all_order: ' + sym + '\n' +
                        json.dumps(resjson, indent=2))
            time.sleep(1)

        self._debug('[GET] get_all_order:\n' + json.dumps(result, indent=2))
        return result

    def get_open_orders(self, symbol=''):
        result = []

        resjson = self.get_all_orders(symbol)
        for res in resjson:
            if res['order_state'] == 'open':
                result.append(res)

        time.sleep(1)

        self._debug('[GET] get_open_orders:\n' + json.dumps(result, indent=2))
        return result

    def cancel_order(self, order_id):
        '''[summary]

        [description]

        Arguments:
            symbol {[type]} -- [description]
            order_id {[type]} -- [description]

        Returns:
            [type] -- [description]
        '''
        url = '/orders/' + order_id
        resjson = self._del(url)

        self._debug('cancel_order: \n' + json.dumps(resjson, indent=2))
        return resjson

    def cancel_all_orders(self):
        orders = self.get_open_orders()
        result = True
        order_ids = []
        for order in orders:
            order_ids.append({'order_id': order['order_id']})

        self._debug('order_ids: \n' + json.dumps(order_ids, indent=2))

        url = '/orders/cancel'
        resjson = self._post(url, order_ids)

        self._debug('cancel_all_order: \n' + json.dumps(resjson, indent=2))

        return result

    def withdraw(self, currency, amount, address):
        '''[summary]

        [description]

        Arguments:
            currency {[type]} -- ['bitcoin', 'litecoin', 'ethereum', 'ethereumc', 'mastercoin', 'zcash', 'monero', 'wire', 'dash', 'ripple', 'eos', 'neo', 'aventus', 'qtum', 'eidoo']
            amount {[type]} -- [description]
            address {[type]} -- [description]

        Returns:
            [type] -- [description]
        '''
        # url = '/withdrawals'
        # data = {
        #     "address": address,
        #     "label": 'api withdraw action',
        #     "amount": amount,
        #     "withdrawal_type": currency.upper(),
        #     'fee': fee,
        #     'asset_pin': asset_pin
        # }

        # result = self._post(url, data)
        # self._debug('limit_buy: \n' + json.dumps(result, indent=2))
        # return result
        raise NotImplementedError()
